package com.tpshion.deploy.handler;

import com.tpshion.deploy.util.AssertUtil;
import com.tpshion.deploy.common.support.BusinessException;
import com.tpshion.deploy.common.constant.ErrorCode;
import com.tpshion.deploy.common.support.Result;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.Objects;

@Slf4j
@RestControllerAdvice
public class GlobleExceptionHandler {

    /**
     * 参数异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result paramExceptionHandle(MethodArgumentNotValidException e) {
        FieldError fieldError = e.getBindingResult().getFieldError();
        String msg = fieldError == null ? "参数错误" : fieldError.getDefaultMessage();

        log.error("ParamException {} url:{} errorMethod:{} errorMsg:{}",
                e.getClass().getName(), getUrl(), getErrorMethodName(e), e.getMessage());
        return Result.fail(msg);
    }

    /**
     * 业务异常处理
     */
    @ExceptionHandler(BusinessException.class)
    public Result businessExceptionHandler(BusinessException e){
        log.error("BusinessException {} url:{} errorMethod:{} errorMsg:{}",
                e.getClass().getName(), getUrl(), getErrorMethodName(e), e.getMessage());
        return Result.error(e);
    }

    /**
     * 系统异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public Result systemExceptionHandler(Exception e){
        log.error("SystemException {} url:{} errorMethod:{} errorMsg:{}",
                e.getClass().getName(), getUrl(), getErrorMethodName(e), e.getMessage(), e);
        return Result.fail(ErrorCode.FAIL);
    }

    private String getUrl(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        return request.getServletPath();
    }

    /**
     * 获取抛出异常的方法
     * @param e
     * @return
     */
    private String getErrorMethodName(Exception e){
        if(Objects.isNull(e)){
            return null;
        }
        if(AssertUtil.class.getName().equals(e.getStackTrace()[0].getClassName()) && e.getStackTrace().length > 1){
            return e.getStackTrace()[1].toString();
        }
        return e.getStackTrace()[0].toString();
    }
}
